<template>
    <canvas :width="width" :height="height" ref="canvasRef"></canvas>
    <br>
    <button @click="rotate">Rotate</button>
</template>
  
<script setup lang="ts">
import { ref, onMounted, computed } from "vue";
import * as GLMatrix from "gl-matrix";
import { loadImage } from "../../util/Util";
const width = ref(700);
const height = ref(700)
const canvasRef = ref<HTMLCanvasElement>()
const webgl = ref<WebGLRenderingContext>()
const programV = ref<WebGLProgram>()

const rotateValue = ref<GLMatrix.mat4>(GLMatrix.mat4.create());
GLMatrix.mat4.rotateZ(rotateValue.value, rotateValue.value, 0)

const glView = computed(() => {
    const mat4 = GLMatrix.mat4.create();
    GLMatrix.mat4.ortho(mat4, 0, width.value, height.value, 0, -1, 1)
    return mat4;
})

const veSource = computed(() => {
    return `
        attribute vec4 a_Position;
        uniform mat4 view;
        uniform mat4 degV;
        attribute vec2 t_Position;
        // 二维坐标
        varying vec2 t_point;
        void main(void){
            gl_Position =  view * a_Position * degV;
            gl_PointSize = 1.0;
            t_point = t_Position;
        }
    `
})

const faSource = computed(() => {
    return `
        precision mediump float;
        varying vec2 t_point;  
        // 取样器，这里可将其理解为纹理对象
        uniform sampler2D u_Sampler;
        void main(void){
            gl_FragColor = vec4(1.0,1.0,0,1);
            // gl_FragColor = vec4(t_point.x,t_point.y,0,1);
            // 通过纹理坐标 取纹理的色系值
            gl_FragColor = texture2D(u_Sampler,t_point);
        }
    `
})

onMounted(() => {
    const gl = canvasRef.value?.getContext('webgl');
    if (!gl) return;
    const veShader = gl.createShader(gl.VERTEX_SHADER);
    const faShader = gl.createShader(gl.FRAGMENT_SHADER);
    if (!veShader || !faShader) return;
    gl.shaderSource(veShader, veSource.value);
    gl.shaderSource(faShader, faSource.value);
    gl.compileShader(veShader);
    gl.compileShader(faShader);

    if (!gl.getShaderParameter(veShader, gl.COMPILE_STATUS)) {
        var err = gl.getShaderInfoLog(veShader);
        alert(err);
        return;
    }
    if (!gl.getShaderParameter(faShader, gl.COMPILE_STATUS)) {
        var err = gl.getShaderInfoLog(faShader);
        alert(err);
        return;
    }

    const program = gl.createProgram();
    if (!program) return;
    gl.attachShader(program, veShader);
    gl.attachShader(program, faShader);
    gl.linkProgram(program);
    gl.useProgram(program);

    if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
        var info = gl.getProgramInfoLog(program);
        throw new Error('Could not compile WebGL program. \n\n' + info);
    }

    const view = gl.getUniformLocation(program, 'view');
    gl.uniformMatrix4fv(view, false, glView.value)


    gl.clearColor(0, 0, 0, 1);
    gl.clear(gl.COLOR_BUFFER_BIT)


    const points = new Float32Array([
        100, 100, 300, 100, 300, 300, 100, 300,
        400, 100, 600, 100, 600, 300, 400, 300,
        100, 400, 300, 400, 300, 600, 100, 600,
        400, 400, 600, 400, 600, 600, 400, 600
    ])

    const BYTE = points.BYTES_PER_ELEMENT;

    const buffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
    gl.bufferData(gl.ARRAY_BUFFER, points, gl.STATIC_DRAW);
    const a_Position = gl.getAttribLocation(program, 'a_Position');
    gl.enableVertexAttribArray(a_Position);
    gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, BYTE * 2, 0)

    const render = () => {
        gl.clearColor(0, 0, 0, 1);
        gl.clear(gl.COLOR_BUFFER_BIT)
        gl.drawArrays(gl.TRIANGLE_FAN, 0, 4)
        gl.drawArrays(gl.TRIANGLE_FAN, 4, 4)
        gl.drawArrays(gl.TRIANGLE_FAN, 8, 4)
        gl.drawArrays(gl.TRIANGLE_FAN, 12, 4);
    }



    const tPoints = new Float32Array([
        0, 1, 1, 1, 1, 0, 0, 0,
        0, 1, 1, 1, 1, 0, 0, 0,
        0, 1, 1, 1, 1, 0, 0, 0,
        0, 1, 1, 1, 1, 0, 0, 0,
    ]);
    const tbuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, tbuffer);
    gl.bufferData(gl.ARRAY_BUFFER, tPoints, gl.STATIC_DRAW);
    const t_Position = gl.getAttribLocation(program, 't_Position')
    gl.enableVertexAttribArray(t_Position)
    gl.vertexAttribPointer(t_Position, 2, gl.FLOAT, false, BYTE * 2, 0)

    const degV = gl.getUniformLocation(program, 'degV');
    gl.uniformMatrix4fv(degV, false, rotateValue.value)


    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true)
    const texture = gl.createTexture();
    if (!texture) return;
    gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D, texture)



    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);

    loadImage(import('./images/basetexture.png')).then(res => {
        if (!res) return;
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, res);

        const u_Sampler = gl.getUniformLocation(program, 'u_Sampler');
        gl.uniform1i(u_Sampler, 0)

        render();
    })
    webgl.value = gl;
    programV.value = program;

})

const id = ref<number>()
const rotate = () => {
    const gl = webgl.value;
    const program = programV.value;
    if (!gl || !program) return
    id.value && cancelAnimationFrame(id.value)

    const render = () => {
        gl.clearColor(0, 0, 0, 1);
        gl.clear(gl.COLOR_BUFFER_BIT)
        gl.drawArrays(gl.TRIANGLE_FAN, 0, 4)
        gl.drawArrays(gl.TRIANGLE_FAN, 4, 4)
        gl.drawArrays(gl.TRIANGLE_FAN, 8, 4)
        gl.drawArrays(gl.TRIANGLE_FAN, 12, 4);
    }

    const _render = () => {
        GLMatrix.mat4.rotateZ(rotateValue.value, rotateValue.value, 0.005);
        const degV = gl.getUniformLocation(program, 'degV');
        gl.uniformMatrix4fv(degV, false, rotateValue.value);
        render();
        id.value = requestAnimationFrame(_render);
    }
    id.value = requestAnimationFrame(_render)

}
</script>
  
<style></style>
  